package com.fenmirs.bookmarks.mvc;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;

/**
 * @author fenmirs
 * @create 2019-05-22 10:46
 * simple description of this file
 */
@Service
public class BookmarksService {
    @Resource
    private BookmarksMapper bookmarksMapper;

    public BookmarksData findDatas(String userId){
        BookmarksData data = new BookmarksData();
        List<BookmarksVo> tList = bookmarksMapper.findAllOfUser(userId);
        Map<String,List<BookmarksVo>> parentMap = new HashMap<>();

        if(CollectionUtils.isNotEmpty(tList)){
            List<BookmarksVo> list = null;
            tList.forEach(t->{
                if(!t.getBookmarksId().equals("0")){
                    String pId = t.getParentDirId();
                    //父级
                    List<BookmarksVo> children = new ArrayList<>();
                    if(parentMap.containsKey(pId)){
                        children = parentMap.get(pId);
                    }
                    //设置排序
                    t.setBookmarkIndex(children.size());
                    children.add(t);
                    parentMap.put(pId,children);
                }
            });

            //组装数据
            list =  parentMap.get("0");
            initChildren(list,parentMap);

            data.setCount(tList.size());
            data.setTree(list);
        }


       return data;
    }

    //组装子节点
    private void initChildren(List<BookmarksVo> list, Map<String, List<BookmarksVo>> parentMap) {
        if(CollectionUtils.isNotEmpty(list)){
            list.forEach(item->{
                List<BookmarksVo> children = parentMap.get(item.getBookmarksId());
                initChildren(children,parentMap);
                item.setChildren(children);
            });

        }
    }

    @Transactional
    public Integer addList(AddParam param) {
        int r = 0;
        if(CollectionUtils.isNotEmpty(param.getList())){
            //初始化插入列表,并将参数列表的id(除0,1,2外)规制为从3开始排列
            List<BookmarksVo> insertList = handelParamList(param.getList());

            if(StringUtils.isNotBlank(param.getUserId())&&!param.getIsForce()){
                /**1.查出数据库中的列表*/
                List<BookmarksVo> tList = bookmarksMapper.findAllOfUser(param.getUserId());
                if(CollectionUtils.isNotEmpty(tList)){
                    //数据库的数据
                    Map<String,BookmarksVo> tIdMap= new HashMap<>();
                    Map<String,List<String>> tParentIdMap = new HashMap<>();
                    dataToMap(tList, tIdMap, tParentIdMap);

                    //上传的数据
                    Map<String,BookmarksVo> idMap= new HashMap<>();
                    dataToMap(insertList, idMap, null);

                    /**2.根据bookmarksId组装列表*/
                    Map<String,String> idChangeMap  = new HashMap<>();
                    idChangeMap.put("maxId", insertList.size()-1+"");
                    for (String id: tParentIdMap.keySet()) {
                        //是否是根目录 或者 已处理过
                        if (!id.equals("0")&&!id.equals("1")&&!id.equals("2") && !idChangeMap.containsKey(id)) {
                            BookmarksVo item = idMap.get(id);
                            BookmarksVo t = tIdMap.get(id);
                            //url不同或者本地标签不存在:添加
                            if (item == null||!item.getBookmarkUrl().equals(t.getBookmarkUrl())){
                                //不存在的都会直接添加至书签栏
                                addNodeAndChildren(t.getParentDirId(),idChangeMap,tIdMap,tParentIdMap,t,insertList);
                            }
                        }
                    }
                }
            }

            /**3.删除数据库相关数据*/
            bookmarksMapper.deleteOfUser(param.getUserId());
            /**3.添加新列表*/
            initList(insertList);//空值替换
            r = bookmarksMapper.addAll(insertList);
            if(r<1){//回滚
                throw new RuntimeException("您的操作没有产生任何效果");
            }
        }
        return r;
    }
    /**
     * 添加节点和子节点
     * @param newPId
     * @param idChangeMap
     * @param parentIdMap
     * @param oo
     * @param list
     */
    private void addNodeAndChildren(String newPId,Map<String,String> idChangeMap,Map<String,BookmarksVo> idMap,Map<String,List<String>> parentIdMap,BookmarksVo oo,List<BookmarksVo> list){
        String newId = idChangeMap.get(oo.getBookmarksId());
        if(newId==null){
            String newMaxId = Integer.parseInt(idChangeMap.get("maxId"))+1+"";
            newId =  newMaxId;
            idChangeMap.put("maxId",newMaxId);//更新最大id
            idChangeMap.put(oo.getBookmarksId(),newId);
        }

        //添加子节点
        List<String> children = parentIdMap.get(oo.getBookmarksId());
        if(CollectionUtils.isNotEmpty(children)){
            for (String childId : children) {
                BookmarksVo child = idMap.get(childId);
                addNodeAndChildren(newId, idChangeMap, idMap,parentIdMap, child, list);
            }
        }

        //添加节点
        oo.setBookmarksId(newId);
        oo.setParentDirId(newPId);
        list.add(oo);
    }
    /**
     * 预处理参数列表
     * @param list
     * @return
     */
    private List<BookmarksVo> handelParamList(List<BookmarksVo> list) {
        if(CollectionUtils.isNotEmpty(list)){
            Map<String,String> cMap = new HashMap<>();//存储变化前后的id
            cMap.put("idIndex","2");//起始ID
            for (BookmarksVo item : list) {
                String pId = item.getParentDirId();
                String id = item.getBookmarksId();

                //id
                id = initNewId(id,cMap);
                //pid
                pId = initNewId(pId,cMap);

                item.setBookmarksId(id);
                item.setParentDirId(pId);
            }
        }
        return list;
    }

    private String initNewId(String id,Map<String,String> cMap){
        if (StringUtils.isNotBlank(id)&&!id.equals("0")&&!id.equals("1")&&!id.equals("2")) {
            if (cMap.containsKey(id)) {
                id = cMap.get(id);
            } else {
                String newId = Integer.parseInt(cMap.get("idIndex"))+1+"";
                cMap.put(id, newId);
                cMap.put("idIndex",newId);//新起始ID
                id = newId;
            }
        }
        return id;
    }

    private void dataToMap(List<BookmarksVo> list, Map<String, BookmarksVo> idMap, Map<String, List<String>> parentIdMap) {
        if(CollectionUtils.isNotEmpty(list)&&(idMap!=null||parentIdMap!=null)){
            for (BookmarksVo item : list) {
                String id = item.getBookmarksId();
                String pId = item.getParentDirId();

                //跳过为0的id
                if(id.equals("0")){
                    continue;
                }

                if (idMap != null) {
                    idMap.put(id, item);
                }

                //父级
                if (parentIdMap != null) {
                    List<String> childrenId = new ArrayList<>();
                    if (parentIdMap.containsKey(pId)) {
                        childrenId = parentIdMap.get(pId);
                    }
                    childrenId.add(id);
                    parentIdMap.put(pId, childrenId);
                }
            }
        }
    }

    @Transactional
    public BookmarksData synchronizeData(AddParam param){
        BookmarksData data = null;
        if(StringUtils.isNotBlank(param.getUserId())){
            addList(param);   //先上传
            data  =  findDatas(param.getUserId());//下载
        }

        //再返回
        return data;
    }


    /**
     * 处理list中为null的值
     * @param list
     */
    private void initList(List<BookmarksVo> list){
        list.forEach(item->{
            item.setId( UUID.randomUUID().toString().replace("-", ""));
            if(StringUtils.isBlank(item.getBookmarkUrl())){
                item.setBookmarkUrl("");
            }
            if(StringUtils.isBlank(item.getBookmarkName())){
                item.setBookmarkName("");
            }
            if(StringUtils.isBlank(item.getParentDirId())){
                item.setParentDirId("0");
            }
            if(StringUtils.isBlank(item.getUserId())){
                item.setUserId("1");
            }
            if(null==item.getBookmarkIndex()){
                item.setBookmarkIndex(0);
            }
            if(null==item.getCreateTime()){
                item.setCreateTime(0);
            }
        });
    }
}
